﻿/**************************************************************
*作者：Leon
*创建时间：2022/4/5 20:26:55
**************************************************************/
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace Lad.DrawProject.Controls;

/// <summary>
/// 颜色视图模型
/// </summary>
public interface IColorViewModel : INotifyPropertyChanged
{
    /// <summary>
    /// 线型颜色
    /// </summary>
    IColorObject LineColor { get; set; }

    /// <summary>
    /// 填充颜色
    /// </summary>
    IColorObject FillColor { get; set; }

    /// <summary>
    /// 阴影颜色
    /// </summary>
    Color ShadowColor { get; set; }

    /// <summary>
    /// 线宽
    /// </summary>
    double LineWidth { get; set; }

}

[Serializable]
public class ColorViewModel : ObservableObject, IColorViewModel
{
    #region 界面使用
    public static Color[] FillColors { get; } = new Color[] { Colors.Red, Colors.Green, Colors.Blue, Colors.White, Colors.Black, Colors.Purple };
    public static Color[] LineColors { get; } = new Color[] { Colors.Red, Colors.Green, Colors.Blue, Colors.White, Colors.Black, Colors.Purple };
    #endregion

    public ColorViewModel()
    {
        LineColor = new ColorObject() { Color = Colors.Gray };
        FillColor = new ColorObject() { Color = Colors.Transparent };
    }
    private IColorObject? _lineColor;
    public IColorObject LineColor
    {
        get
        {
            return _lineColor!;
        }
        set
        {
            if (_lineColor != value)
            {
                if (_lineColor != null && _lineColor is ColorObject _lineColor1)
                {
                    _lineColor1.PropertyChanged -= ColorViewModel_PropertyChanged;
                }
                SetProperty(ref _lineColor, value);
                if (_lineColor != null && _lineColor is ColorObject _lineColor2)
                {
                    _lineColor2.PropertyChanged += ColorViewModel_PropertyChanged;
                }
            }
            else
            {
                OnPropertyChanged(nameof(LineColor));
            }
        }
    }

    private IColorObject? _fillcolor;
    public IColorObject FillColor
    {
        get
        {
            return _fillcolor!;
        }
        set
        {
            if (_fillcolor != value)
            {
                if (_fillcolor != null && _fillcolor is ColorObject colorObject1)
                {
                    colorObject1.PropertyChanged -= ColorViewModel_PropertyChanged;
                }
                SetProperty(ref _fillcolor, value);
                if (_fillcolor != null && _fillcolor is ColorObject colorObject2)
                {
                    colorObject2.PropertyChanged += ColorViewModel_PropertyChanged;
                }
            }
            else
            {
                OnPropertyChanged(nameof(FillColor));
            }
        }
    }

    private void ColorViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {

        if (sender == LineColor)
        {
            OnPropertyChanged(nameof(LineColor));
        }
        else if (sender == FillColor)
        {
            OnPropertyChanged(nameof(FillColor));
        }
    }

    private Color _shadowColor = Colors.Transparent;
    public Color ShadowColor
    {
        get
        {
            return _shadowColor;
        }
        set
        {
            if (!SetProperty(ref _shadowColor, value))
            {
                OnPropertyChanged(nameof(ShadowColor));
            }
        }
    }

    private double _lineWidth = 1;
    public double LineWidth
    {
        get
        {
            return _lineWidth;
        }
        set
        {
            if (!SetProperty(ref _lineWidth, value))
            {
                OnPropertyChanged(nameof(LineWidth));
            }
        }
    }




    private LineDashStyle _lineDashStyle = LineDashStyle.None;
    /// <summary>
    /// 虚线类型样式
    /// </summary>
    public LineDashStyle LineDashStyle
    {
        get
        {
            return _lineDashStyle;
        }
        set
        {
            if (!SetProperty(ref _lineDashStyle, value))
            {
                OnPropertyChanged(nameof(LineDashStyle));
            }
        }
    }
}

/// <summary>
/// 序列化颜色对象
/// </summary>
[Serializable]
public class ColorObject : ObservableObject, IColorObject
{
    public ColorObject()
    {
    }

    private void GradientStop_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.OldItems != null)
        {
            foreach (var old in e.OldItems.OfType<GradientStop>())
            {
                old.PropertyChanged -= GradientStop_PropertyChanged;
            }
        }
        if (e.NewItems != null)
        {
            foreach (var old in e.NewItems.OfType<GradientStop>())
            {
                old.PropertyChanged += GradientStop_PropertyChanged;
            }
        }
    }

    private void GradientStop_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        OnPropertyChanged(nameof(GradientStop));
    }


    public void BrushTypeChanged()
    {
        if (BrushType == BrushType.LinearGradientBrush || BrushType == BrushType.RadialGradientBrush)
        {
            if (GradientStop == null)
            {
                GradientStop = new ObservableCollection<GradientStop>();
                GradientStop.Add(new GradientStop(Color, 0));
                GradientStop.Add(new GradientStop(Colors.Gray, 1));
                SelectedGradientStop = GradientStop.FirstOrDefault();
                OnPropertyChanged(nameof(GradientStop));
            }
        }
    }

    private BrushType _brushType = BrushType.SolidColorBrush;
    public BrushType BrushType
    {
        get
        {
            return _brushType;
        }
        set
        {
            if (SetProperty(ref _brushType, value))
            {
                BrushTypeChanged();
            }
        }
    }

    private Color _color = new();
    public Color Color
    {
        get
        {
            return _color;
        }
        set
        {
            SetProperty(ref _color, value);

        }
    }

    private ObservableCollection<GradientStop>? _gradientStop;
    public ObservableCollection<GradientStop>? GradientStop
    {
        get
        {
            return _gradientStop;
        }
        set
        {
            if (_gradientStop != value)
            {
                if (_gradientStop != null)
                {
                    _gradientStop.CollectionChanged -= GradientStop_CollectionChanged;
                }
                SetProperty(ref _gradientStop, value);
                if (_gradientStop != null)
                {
                    _gradientStop.CollectionChanged += GradientStop_CollectionChanged;
                }
            }
        }
    }

    private GradientStop? _selectedGradientStop;
    public GradientStop? SelectedGradientStop
    {
        get
        {
            return _selectedGradientStop;
        }
        set
        {
            SetProperty(ref _selectedGradientStop, value);
        }
    }
    private Point _startPoint;
    public Point StartPoint
    {
        get
        {
            return _startPoint;
        }
        set
        {
            SetProperty(ref _startPoint, value);
        }
    }

    private Point _endPoint;
    public Point EndPoint
    {
        get
        {
            return _endPoint;
        }
        set
        {
            SetProperty(ref _endPoint, value);
        }
    }

    private double _opacity = 1;
    public double Opacity
    {
        get
        {
            return _opacity;
        }
        set
        {
            SetProperty(ref _opacity, value);
        }
    }

    private double _light;
    public double Light
    {
        get
        {
            return _light;
        }
        set
        {
            SetProperty(ref _light, value);
        }
    }

    private string? _image;
    public string? Image
    {
        get
        {
            return _image;
        }
        set
        {
            SetProperty(ref _image, value);
        }
    }

    private LinearOrientation _linearOrientation;
    public LinearOrientation LinearOrientation
    {
        get
        {
            return _linearOrientation;
        }
        set
        {
            SetProperty(ref _linearOrientation, value);
        }
    }

    private RadialOrientation _radialOrientation;
    public RadialOrientation RadialOrientation
    {
        get
        {
            return _radialOrientation;
        }
        set
        {
            SetProperty(ref _radialOrientation, value);
        }
    }

    private int _angle;
    public int Angle
    {
        get
        {
            return _angle;
        }
        set
        {
            SetProperty(ref _angle, value);
        }
    }

    private int _subType;

    public int SubType
    {
        get
        {
            return _subType;
        }
        set
        {
            SetProperty(ref _subType, value);
        }
    }

    public ICommand AddGradientStopCommand
    {
        get
        {
            return new RelayCommand(() =>
            {
                if (GradientStop == null)
                    throw new InvalidOperationException("GradientStop 为 null");
                var offset = GradientStop.Skip(GradientStop.Count - 2).Select(p => p.Offset).Average();
                GradientStop.Add(new GradientStop(Colors.Gray, offset));
            });
        }
    }
    public ICommand DeleteGradientStopCommand
    {
        get
        {
            return new RelayCommand(() =>
            {
                if (SelectedGradientStop != null && GradientStop != null && GradientStop.Count > 2)
                {
                    GradientStop.Remove(SelectedGradientStop);
                }
            });
        }
    }
}

public interface IColorObject
{
    BrushType BrushType { get; set; }
    Color Color { get; set; }

    /// <summary>
    /// 渐变笔刷
    /// </summary>
    ObservableCollection<GradientStop>? GradientStop { get; set; }
    Point StartPoint { get; set; }
    Point EndPoint { get; set; }
    double Opacity { get; set; }
    LinearOrientation LinearOrientation { get; set; }
    RadialOrientation RadialOrientation { get; set; }
    int Angle { get; set; }
    string? Image { get; set; }
    int SubType { get; set; }
}

public class GradientStop : ObservableObject
{
    public GradientStop()
    {

    }
    public GradientStop(Color color, double offset)
    {
        Color = color;
        Offset = offset;
    }
    private Color _color = new Color();
    public Color Color
    {
        get
        {
            return _color;
        }
        set
        {
            SetProperty(ref _color, value);
        }
    }

    private double _offset;
    public double Offset
    {
        get
        {
            return _offset;
        }
        set
        {
            SetProperty(ref _offset, value);
        }
    }



}

public enum BrushType
{
    None,
    SolidColorBrush,
    LinearGradientBrush,
    RadialGradientBrush,
    ImageBrush,
    VisualBrush,
    DrawingBrush
}

public enum RadialOrientation
{
    [Description("中心")]
    Center,
    [Description("左上")]
    LeftTop,
    [Description("右上")]
    RightTop,
    [Description("右下")]
    RightBottom,
    [Description("左下")]
    LeftBottom,
}

public enum LinearOrientation
{
    [Description("左到右")]
    LeftToRight,
    [Description("左上到右下")]
    LeftTopToRightBottom,
    [Description("上到下")]
    TopToBottom,
    [Description("右上到左下")]
    RightTopToLeftBottom,
    [Description("右到左")]
    RightToLeft,
    [Description("右下到左上")]
    RightBottomToLeftTop,
    [Description("下到上")]
    BottomToTop,
    [Description("左下到右上")]
    LeftBottomToRightTop
}

public enum LineDashStyle
{
    None,
    Dash1,
    Dash2,
    Dash3,
    Dash4,
    Dash5,
    Dash6,
    Dash7,
    Dash8,
    Dash9,
    Dash10,
    Dash11,
    Dash12,
    Dash13,
    Dash14,
    Dash15,
    Dash16,
    Dash17,
    Dash18,
    Dash19,
    Dash20,
    Dash21
}
